/******************************************************************************
 *
 * Project:		mGameEngine
 * File:		lock.cpp
 * Author:		karooolek
 * Created on:	2009-02-27
 *
 ******************************************************************************/

#include "lock.h"

Lock::Lock(bool locked, float timeout) :
	_mutex(), _timeout(timeout)
{
#ifdef _WIN32
	_mutex = CreateMutex(NULL, FALSE, NULL);
#else
	pthread_mutex_init(&_mutex, NULL);
#endif

	// initial lock
	if(locked)
	{
		lock();
	}
}

Lock::Lock(const Lock &lock) :
	_mutex(), _timeout(lock._timeout)
{
#ifdef _WIN32
	_mutex = CreateMutex(NULL, FALSE, NULL);
#else
	pthread_mutex_init(&_mutex, NULL);
#endif
}

Lock::~Lock()
{
#ifdef _WIN32
	CloseHandle(_mutex);
	_mutex = 0;
#else
	pthread_mutex_destroy(&_mutex);
#endif
}

void Lock::lock()
{
#ifdef _WIN32
	WaitForSingleObject(_mutex, INFINITE);
#else
	pthread_mutex_lock(&_mutex);
#endif
}

bool Lock::tryLock()
{
#ifdef _WIN32
	return WaitForSingleObject(_mutex, _timeout >= 0.0f ? DWORD(1000 * _timeout) : INFINITE) == WAIT_OBJECT_0;
#else
	if (_timeout < 0.0f) {			// infinite
		return pthread_mutex_lock(&_mutex) == 0;
	}

	timespec timeout;
	clock_gettime(CLOCK_REALTIME, &timeout);
	timeout.tv_sec += (int)_timeout;
	timeout.tv_nsec += 10E8*(_timeout -  (float)(int)_timeout);
    if (timeout.tv_nsec >= 1000000000L) {
    	timeout.tv_sec++;
    	timeout.tv_nsec -= 1000000000L;
    }

	return pthread_mutex_timedlock(&_mutex, &timeout) == 0;
#endif
}

void Lock::unlock()
{
#ifdef _WIN32
	ReleaseMutex(_mutex);
#else
	pthread_mutex_unlock(&_mutex);
#endif
}
